//*****************************************************************
// Controller.h
//
//  Created on: Jan 21, 2012
//      Author: Christopher Wood
//              Robert Livosi
//
//  $Id: Controller.h 33 2012-01-30 13:13:24Z caw4567 $
//*****************************************************************

#ifndef CONTROLLER_H_
#define CONTROLLER_H_

#include "IOThreadGroup.h"
#include "ControlAlgorithm.h"

// Resolve forward declaration
class IOThreadGroup;

/**
 * This class is responsible for performing the PID transformation routine
 * using the input analog signal from the plant in order to drive the
 * plant at the next discrete instance in time.
 */
class Controller
{
public:
	/**
	 * Create a new controller thread that will manage the discrete-time transformations.
	 *
	 * @param algorithmType - the type of transform/control algorithm to be used.
	 */
	Controller(AlgorithmType algorithmType);

	/**
	 * Default destructor.
	 */
	virtual ~Controller();

	/**
	 * Start the thread.
	 */
	void run();

	/**
	 * Retrieve the I/O thread group associated with this transform object.
	 *
	 * @return a pointer to the I/O thread group.
	 */
	IOThreadGroup* getIOGroup();

	/**
	 * Retrieve the current control algorithm being used.
	 *
	 * @return a pointer to the current control algorithm.
	 */
	ControlAlgorithm* getAlgorithm();

	/**
	 * Retrieve the control execution semaphore used to trigger a conversion.
	 *
	 * @return a pointer to the control semaphore.
	 */
	sem_t* getControlSem();

	/**
	 * Set the thread state of this transform thread.
	 *
	 * @param alive - boolean flag indicating the alive state of this thread.
	 */
	void setThreadState(bool alive);

	/**
	 * Determine if this thread is still alive (or should still be alive)
	 *
	 * @return true if still alive, false otherwise.
	 */
	bool isAlive();

	/**
	 * Release this thread from its semaphore.
	 */
	void release();

	/**
	 * Set the IO group that is used to drive this controller.
	 *
	 * @param ioGroup - the desired ioGroup object (a pointer to it)
	 */
	void setIOGroup(IOThreadGroup* ioGroup);

	/**
	 * Set the new reference value (set point).
	 *
	 * @param ref - the new reference value.
	 */
	void setReference(float ref);

	/**
	 * Retrieve the reference parameter.
	 *
	 * @return reference;
	 */
	float getReference();

	/**
	 * Method that is used to prompt the user for the
	 * new algorithm parameters.
	 *
	 * @return a string for the user to interpret.
	 */
	string getParamString();

	/**
	 * Set the parameters of the algorithm.
	 *
	 * @param params - string of new parameters
	 * @returns true if parsing was successful, false otherwise.
	 */
	bool setParams(string params);

	/**
	 * Retrieve the update semaphore.
	 *
	 * @return update semaphore.
	 */
	sem_t* getUpdateSemaphore();

	/**
	 * Reset the controller and control algorithm.
	 */
	void reset();

	/**
	 * Retrieve the controller wait tick.
	 *
	 * @return waitTick
	 */
	uint8_t getWaitTick();

	/**
	 * Decrement the wait tick for the controller.
	 */
	void decrementWaitTick();

private:
	// The internal control algorithm
	ControlAlgorithm* algorithm;

	// The IO group used to drive this controller
	IOThreadGroup* ioGroup;

	// The incoming reference signal we are balancing against
	volatile float reference;

	// Our execution semaphore
	sem_t controlSem;

	// The transform thread unique ID
	pthread_t controlThreadID;

	// Boolean flag controlling execution
	bool alive;

	// Update semaphore
	sem_t updateSem;

	// Counter that controls settling of the controller
	uint8_t waitTick;

	// The number of cycles to wait before resuming normal operation
	static const uint8_t RESET_CYCLES = 100;
};

#endif /* CONTROLLER_H_ */
